﻿using Common.ORM.Repository;
using Microsoft.Extensions.DependencyInjection;
using sixgod.Common.Model;
using sixgod.Dtos.System;
using sixgod.Model.Attribute;
using sixgod.Model.System;
using sixgod.Model.System.Dictionary;
using SqlSugar;
using System.Linq.Expressions;
using AutoMapper;
using FreeRedis;
using Masuit.Tools;
using Masuit.Tools.Linq;
using sixgod.Common;
using sixgod.Common.Extension;

namespace sixgod.Service.Dictionary.Implementation;

[Di(typeof(IDictionaryService),ServiceLifetime.Singleton)]
public class DictionaryService:Repository<SystemDictionary>,IDictionaryService
{
    private const string CACHE_DIC_TYPE_CODE = "PREVENT_DIC_TYPE_CODE";
    private const string CACHE_DIC_ITEM_VALUE = "PREVENT_DIC_ITEM_VALUE";

    private ISqlSugarClient _db;
    private IMapper _mapper;
    private RedisClient _redisClient;
    /// <summary>Initializes a new instance of the <see cref="T:System.Object" /> class.</summary>
    public DictionaryService(ISqlSugarClient db, IMapper mapper, RedisClient redisClient): base(redisClient,db)
    {
        _db = db;
        _mapper = mapper;
        _redisClient = redisClient;
    }

    /// <summary>
    /// 字典服务初始化
    /// </summary>
    /// <returns></returns>
    public async Task Init()
    {
        // 缓存数据 并将防止重复的存入缓存
        var dic = await GetAllList();
        var items = await GetAllListItem();

        await _redisClient.DelAsync(CACHE_DIC_TYPE_CODE);
        await _redisClient.SAddAsync(CACHE_DIC_TYPE_CODE,dic.Select(r=>r.Code).ToArray());

        foreach (var item in dic.Where(item => items.Any(r=>r.ParentCode == item.Id)))
        {
            await _redisClient.DelAsync(CACHE_DIC_ITEM_VALUE+item.Id);
            await _redisClient.SAddAsync(CACHE_DIC_ITEM_VALUE+item.Id,items.Where(r=>r.ParentCode==item.Id).Select(r=>r.Value).ToArray());
        }
    }

    /// <summary>
    /// 从缓存获取所有字典类型
    /// </summary>
    /// <returns></returns>
    public Task<List<SystemDictionary>> GetList()
    {
        return GetAllList();
    }

    /// <summary>
    /// 判断字典项的值是否存在
    /// </summary>
    /// <param name="parentCode">字典类型</param>
    /// <param name="value">字典值</param>
    /// <returns></returns>
    private Task<bool> ItemValueIsExits(string parentCode,string value)
    {
        return _redisClient.SIsMemberAsync(CACHE_DIC_ITEM_VALUE+parentCode,value);
    }
    private Task<bool> TypeCodeIsExits(string typeCode)
    {
        return _redisClient.SIsMemberAsync(CACHE_DIC_TYPE_CODE,typeCode);
    }

    private async Task<List<SystemDictionary>> GetAllList()
    {
        var str = await _redisClient.GetAsync(CacheKeyConsts.DIC_LIST);
        if (str.IsNullOrEmpty())
        {
            var list = await GetListAsync(r => r.IsDelete == 0);
            await _redisClient.SetAsync(CacheKeyConsts.DIC_LIST, list.ToJsonString(), 3600 * 24);
            return list;
        }

        return str.ToObj<List<SystemDictionary>>();
    }

    private async Task<List<DictionaryItem>> GetAllListItem()
    {
        var str = await _redisClient.GetAsync(CacheKeyConsts.DIC_ITEM_LIST);
        if (str.IsNullOrEmpty())
        {
            // var list = await GetListAsync(r => r.IsDelete == 0);
            var list = await _db.Queryable<DictionaryItem>().Where(r=>r.IsDelete == 0).ToListAsync();
            await _redisClient.SetAsync(CacheKeyConsts.DIC_ITEM_LIST, list.ToJsonString(), 3600 * 24);
            return list;
        }

        return str.ToObj<List<DictionaryItem>>();
    }

    /// <summary>
    /// 刷新缓存字典数据
    /// </summary>
    /// <returns></returns>
    private async Task RefreshCacheData()
    {
        var list = await GetListAsync(r => r.IsDelete == 0);
        await _redisClient.SetAsync(CacheKeyConsts.DIC_LIST, list.ToJsonString(), 3600 * 24);
        await Init();
    }

    /// <summary>
    /// 刷新字典值数据
    /// </summary>
    /// <returns></returns>
    private async Task RefreshItemCacheData()
    {
        var list = await _db.Queryable<DictionaryItem>().Where(r=>r.IsDelete == 0).ToListAsync();
        await _redisClient.SetAsync(CacheKeyConsts.DIC_ITEM_LIST, list.ToJsonString(), 3600 * 24);
        await Init();
    }

    /// <summary>
    /// 字典类型分页数据
    /// </summary>
    /// <param name="search"></param>
    /// <returns></returns>
    public async Task<PageResponseResult<DictionaryDto>> GetPageList(DicQueryModel search)
    {
        PageResponseResult<DictionaryDto> result = new PageResponseResult<DictionaryDto>();

        Expression<Func<SystemDictionary,bool>> exp = r => true;
        Expression<Func<SystemDictionary,bool>> exp2 = r => r.Name.StartsWith(search.Name);
        // exp.AndIf(!search.Name.IsNullOrEmpty(), r => r.Name.Contains(search.Name!));
        exp = exp.AndIf(!search.Name.IsNullOrEmpty(),r=>r.Name.Contains(search.Name!));

        var list = (await GetAllList()).Where(exp.Compile()).ToList();

        result.Data = _mapper.Map<List<DictionaryDto>>(list.Skip(search.Skip()).Take(search.PageSize));
        result.Count = list.Count;

        return result;
    }

    public async Task<List<DicItemDto>> GetItemList(string code)
    {
        var list = await GetAllListItem();
        return _mapper.Map<List<DicItemDto>>(list.Where(r=>r.ParentCode==code).ToList());
    }

    public async Task<List<DictionaryItem>> GetItemSourceList(string code)
    {
        var list = await GetAllListItem();
        return list.Where(r=>r.ParentCode==code).ToList();
    }

    /// <summary>
    /// 通过字典类型获取字典项
    /// </summary>
    /// <param name="code"></param>
    /// <returns></returns>
    public async Task<List<DictionaryItem>> GetDicItemList(string code)
    {
        var dic = await GetListByRedis(CacheKeyConsts.DIC_LIST);
        var item = dic.FirstOrDefault(r=>r.Code == code);
        if (item!=null)
        {
            return await GetItemSourceList(item.Id);
        }

        return null;
    }

    /// <summary>
    /// 插入数据
    /// </summary>
    /// <param name="dictionary"></param>
    /// <returns></returns>
    public async Task<bool> InsertSystemDictionaryAsync(SystemDictionary dictionary)
    {
        var res = await InsertAsync(dictionary);
        if (res)
        {
            await RefreshCacheData();
        }
        return res;
    }

    /// <summary>
    /// 更新数据
    /// </summary>
    /// <param name="dictionary"></param>
    /// <returns></returns>
    public async Task<bool> UpdateSystemDictionaryAsync(SystemDictionary dictionary)
    {
        var res = await _db.Updateable(dictionary).Where(r=>r.Id==dictionary.Id).ExecuteCommandHasChangeAsync();
        if (res)
        {
            await RefreshCacheData();
        }
        return res;
    }

    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="code"></param>
    /// <returns></returns>
    public Task<bool> DeleteSystemDictionaryAsync(string code)
    {
        // todo 类型在删除后仍然存在唯一约束，需要想办法处理
        return this.AsUpdateable()
            .SetColumns(r=>new SystemDictionary(){IsDelete = 1,UpdateTime = DateTime.Now,UpdateUser = "admin"})
            .Where(r=>r.Id == code)
            .ExecuteCommandHasChangeAsync();
    }

    /// <summary>
    /// 获取字典项
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="code">字典类型代码</param>
    /// <returns></returns>
    public async Task<List<DicItemDto>> GetDicList(string code)
    {
        var dicType = (await GetAllList()).First(r=>r.Code==code);
        var list = await GetAllListItem();

        return _mapper.Map<List<DicItemDto>>(list.Where(r=>r.ParentCode==dicType.Id));
    }

    /// <summary>
    /// 新增字典项
    /// </summary>
    /// <param name="item"></param>
    /// <returns></returns>
    public async Task<bool> InsertSystemDictionaryItemAsync(DictionaryItem item)
    {
        var isExit = await this.ItemValueIsExits(item.ParentCode,item.Value);
        if (isExit)
        {
            throw new Exception("该字典项的值已存在");
        }
        var res = await _db.Insertable(item).ExecuteCommandIdentityIntoEntityAsync();
        if (res)
        {
            await RefreshItemCacheData();
        }
        return res;
    }

    /// <summary>
    /// 更新字典项
    /// </summary>
    /// <param name="item"></param>
    /// <returns></returns>
    public async Task<bool> UpdateSystemDictionaryItemAsync(DictionaryItem item)
    {
        var isExit = await this.ItemValueIsExits(item.ParentCode,item.Value);
        if (isExit)
        {
            throw new Exception("该字典项的值已存在");
        }
        var res = await _db.Updateable<DictionaryItem>(item)
            .Where(r=>r.Id == item.Id)
            .ExecuteCommandHasChangeAsync();

        if (res)
        {
            await RefreshItemCacheData();
        }

        return res;
    }

    /// <summary>
    /// 删除字典项
    /// </summary>
    /// <param name="code"></param>
    /// <returns></returns>
    public async Task<bool> DeleteSystemDictionaryItemAsync(string code)
    {
        var res = await _db.Updateable<DictionaryItem>()
            .SetColumns(r=>new DictionaryItem(){IsDelete = 1})
            .Where(r=>r.Id == code)
            .ExecuteCommandHasChangeAsync();
        if (res)
        {
            await RefreshItemCacheData();
        }

        return res;
    }
}